<?php

declare(strict_types=1);
/*
 * @Description: 个推service类
 * @Author: QianLong
 * @Date: 2019-10-13 12:39:05
 * @LastEditors    : QianLong
 * @LastEditTime   : 2023-09-07 14:57:39
 */

namespace App\Service\File;

use App\Exception\ApiException;
use Yurun\Util\HttpRequest;
class Qiniu
{
    protected $serverInfo = [];
    protected $http = null;
    public function __construct($serverInfo)
    {
        $this->serverInfo = $serverInfo;
        $this->http = new HttpRequest;
    }
    public function uploadFile($object, $Path,$fileName, $dead = 3600)
    {
        $url = $this->getUploadUrl();
        $post_data = array(
            'file' => new \CURLFile($Path),
            'key' => $object,
            'fileName' => $fileName,
        );

        $putPolicy = [
            'scope' => $this->serverInfo['qiniu_bucket'] . ':' . $object,
            'deadline' => time() + $dead, //有效期10分钟
            'returnBody' => '{"name":$(fname),"size":$(fsize),"w":$(imageInfo.width),"h":$(imageInfo.height),"hash":$(etag),"key":$(key)}',
        ];

        $post_data['token'] = $this->makeToken($putPolicy);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
        $info = curl_exec($ch);
        $info = empty($info)?[]:json_decode($info,true);
        if (!isset($info['key']) || empty($info['key'])) {
            throw new ApiException(-1,$info['error']);
        }
    }
    public function getUploadUrl($isJs = true,$region=null)
    {
        $prefix = 'http://up';
        if ($isJs == true) {
            $prefix = 'http://upload';
        }
        if (empty($region)) {
            $region = $this->serverInfo['qiniu_region'];
        }
        switch ($region) {
            case 'z0':
                return $prefix. '.qiniup.com';
                break;
            default:
                return $prefix . '-'. $region.'.qiniup.com';
                break;
        }
    }
    public function objManageUrl($region=null)
    {
        if (empty($region)) {
            $region = $this->serverInfo['qiniu_region'];
        }
        return 'http://rs-'. $region.'.qiniuapi.com';
    }
    public function getUrl($object)
    {
        $url = rtrim($this->serverInfo['qiniu_url'], '/');
        return $url . '/' . $object;
    }
    public function deleteFile($object, $bucket ='', $region = '')
    {
        if (empty($bucket)) {
            $bucket = $this->serverInfo['qiniu_bucket'];
        }
        $url = $this->objManageUrl($region);
        $path = '/delete/' . $this->urlsafe_b64encode($bucket . ':' . $object);
        $headers = $this->authorizationV2($url . $path, 'POST', null, 'application/x-www-form-urlencoded');
        $response = $this->http->headers($headers)->post($url . $path,null,'json');
        $result = $response->body();
        if (!empty($result)) {
            $result = json_decode($result,true);
            if (isset($result['error']) && !empty($result['error'])) {
                throw new ApiException(-1, $result['error']);
            }
        }
    }
	/**
	 * URL安全的base64加密
	 * @param    [type]        $string [description]
	 * @return   [type]                [description]
	 */
	private function urlsafe_b64encode($string) {
		$data = base64_encode($string);
		$data = str_replace(array('+', '/'), array('-', '_'), $data);
		return $data;
	}
	/**
	 * 生成token
	 * @param    [type]        $policy [description]
	 * @return   [type]                [description]
	 */
	private function makeToken($policy) {
		$putPolicy = json_encode($policy); //转为json
		$encodedPutPolicy = $this->urlsafe_b64encode($putPolicy);
		$encodedSign = $this->makeSign($encodedPutPolicy);
		$uploadToken = $this->serverInfo['qiniu_ak'] . ':' . $encodedSign . ':' . $encodedPutPolicy;
		return $uploadToken;
	}
	/**
	 * 生成签名
	 * @param    [type]        $encodedPutPolicy [description]
	 * @return   [type]                          [description]
	 */
	private function makeSign($encodedPutPolicy) {
		$sign = hash_hmac("sha1", $encodedPutPolicy, $this->serverInfo['qiniu_sk'], true);
		$encodedSign = $this->urlsafe_b64encode($sign);
		return $encodedSign;
	}
    public function authorizationV2($url, $method, $body = null, $contentType = null)
    {
        $headers = [];
        $parseUrl = parse_url($url);
        $result['Host'] = $parseUrl['host'];
        if ($contentType != null) {
            $headers['Content-Type'] = $contentType;
            $result['Content-Type'] = $contentType;
        }
        $signDate = gmdate('Ymd\THis\Z');
        $headers['X-Qiniu-Date'] = $signDate;
        $result['X-Qiniu-Date'] = $signDate;

        list($sign) = $this->signQiniuAuthorization($url, $method, $body, $headers);
        $result['Authorization'] = 'Qiniu ' . $sign;
        return $result;
    }
    public function signQiniuAuthorization($urlString, $method = "GET", $body = "", $headers = null)
    {
        $url = parse_url($urlString);
        if (!$url) {
            return array(null, new \Exception("parse_url error"));
        }

        // append method, path and query
        if ($method === "") {
            $data = "GET ";
        } else {
            $data = $method . " ";
        }
        if (isset($url["path"])) {
            $data .= $url["path"];
        }
        if (isset($url["query"])) {
            $data .= "?" . $url["query"];
        }

        // append Host
        $data .= "\n";
        $data .= "Host: ";
        if (isset($url["host"])) {
            $data .= $url["host"];
        }
        if (isset($url["port"]) && $url["port"] > 0) {
            $data .= ":" . $url["port"];
        }

        // try append content type
        if ($headers != null && isset($headers["Content-Type"])) {
            // append content type
            $data .= "\n";
            $data .= "Content-Type: " . $headers["Content-Type"];
        }

        // try append xQiniuHeaders
        if ($headers != null) {
            $headerLines = array();
            $keyPrefix = "X-Qiniu-";
            foreach ($headers as $k => $v) {
                if (strlen($k) > strlen($keyPrefix) && strpos($k, $keyPrefix) === 0) {
                    array_push(
                        $headerLines,
                        $k . ": " . $v
                    );
                }
            }
            if (count($headerLines) > 0) {
                $data .= "\n";
                sort($headerLines);
                $data .= implode("\n", $headerLines);
            }
        }

        // append body
        $data .= "\n\n";
        if (
            !is_null($body)
            && strlen($body) > 0
            && isset($headers["Content-Type"])
            && $headers["Content-Type"] != "application/octet-stream"
        ) {
            $data .= $body;
        }

        return array($this->sign($data), null);
    }
    public function sign($data)
    {
        $hmac = hash_hmac('sha1', $data, $this->serverInfo['qiniu_sk'], true);
        return $this->serverInfo['qiniu_ak'] . ':' . $this->urlsafe_b64encode($hmac);
    }
}
